package xyz.canran.project.algorithm.rate.limiter;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;

/**
 * 漏桶限速器
 * @author xiaobao
 *
 */
public class LeakyBucketRateLimiter {

    private static final Logger log = LoggerFactory.getLogger(LeakyBucketRateLimiter.class);

    private final int limit;
    private final long interval;
    private LinkedBlockingQueue<Character> waterBucketQueue;

    public LeakyBucketRateLimiter(int capacity, long interval, int limit) {
        this.limit = limit;
        this.interval = interval;
        this.waterBucketQueue = new LinkedBlockingQueue<>(capacity);
        startDropping();
    }

   private void startDropping() {
       new Thread(() -> {
           while (true) {
               try{
                   TimeUnit.MILLISECONDS.sleep(interval/limit);
               } catch (InterruptedException ignored) {
                   log.error("Dropping buckets failed", ignored);
               }
               // 通过队列弹出，模拟桶漏水
               Character c = waterBucketQueue.poll();
               if (c != null) {
                   log.info("Dropping buckets successfully, water bucket queue size: {}", waterBucketQueue.size());
               } else {
                   log.info("Dropping buckets failed, water bucket queue size: 0");
               }
           }

       }).start();
   }


   public boolean limit() {
       log.info("Trying to acquire water bucket, water bucket queue size: {}", waterBucketQueue.size());
       return waterBucketQueue.offer(Character.MIN_VALUE);
   }

}
